package io.moquette.chat;

import java.net.URISyntaxException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.fusesource.mqtt.client.BlockingConnection;
import org.fusesource.mqtt.client.MQTT;
import org.fusesource.mqtt.client.Message;
import org.fusesource.mqtt.client.QoS;
import org.fusesource.mqtt.client.Topic;
import org.fusesource.mqtt.client.Tracer;
import org.fusesource.mqtt.codec.MQTTFrame;

import com.test.message.AbstractMessage;
import com.test.message.OnlineUserMessage;
import com.test.message.TextMessage;
import com.test.message.builder.MessageBuiler;
import com.test.message.wrapper.Payload;
import com.test.utils.SerializationUtil;

public class ChatService {
	
	private static MQTT mqtt;
	private static BlockingConnection connection;
	private final static String CONNECTION_STRING = "tcp://localhost:1883";
	private final static boolean CLEAN_START = false;
	private final static short KEEP_ALIVE = 5;// 低耗网络，但是又需要及时获取数据，心跳30s

	public final static long RECONNECTION_ATTEMPT_MAX = 6;
	public final static long RECONNECTION_DELAY = 2000;

	public final static int SEND_BUFFER_SIZE = 2 * 1024 * 1024;// 发送最大缓冲为2M
	
	private static ExecutorService executorService = Executors.newCachedThreadPool();
	
	private static String clientId;
	
	static {
		try {
			mqtt = new MQTT();
			// 设置服务端的ip
			mqtt.setHost(CONNECTION_STRING);
			// 连接前清空会话信息
			mqtt.setCleanSession(CLEAN_START);
			// 设置重新连接的次数
//			mqtt.setReconnectAttemptsMax(RECONNECTION_ATTEMPT_MAX);
			// 设置重连的间隔时间
			mqtt.setReconnectDelay(RECONNECTION_DELAY);
			// 设置心跳时间
			mqtt.setKeepAlive(KEEP_ALIVE);
			// 设置缓冲的大小
//			mqtt.setSendBufferSize(SEND_BUFFER_SIZE);
			mqtt.setWillQos(QoS.AT_LEAST_ONCE);	
			// 设置跟踪器
			mqtt.setTracer(new Tracer() {
				@Override
				public void onReceive(MQTTFrame frame) {
					System.out.println("recv: " + frame);
				}

				@Override
				public void onSend(MQTTFrame frame) {
					System.out.println("send: " + frame);
				}

				@Override
				public void debug(String message, Object... args) {
					System.out.println(String.format("debug: " + message, args));
				}
			});
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
	}
	

	public boolean doLogin(String username, String password){
		try {
			clientId = username;
			mqtt.setClientId(username);
			mqtt.setUserName(username);
			mqtt.setPassword(password);
			// 创建连接 ,使用阻塞式
			connection = mqtt.blockingConnection();
			connection.connect();
			boolean connected = connection.isConnected();
			if(connected) {
				subscribe();
			}
			return connected;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	
	public void subscribe(){
		try {
			Topic[] topics = { new Topic(com.test.topic.Topic.CHAT, QoS.AT_MOST_ONCE) };
			// 订阅相关的主题信息
			connection.subscribe(topics);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public Message getMessage() {
		Message message = null;
		try {
			message = connection.receive();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return message;
	}
	
	/*public void listen(){
		executorService.submit(new Callable<Void>() {
			@Override
			public Void call() throws Exception {
				Topic[] topics = { new Topic(clientId, QoS.AT_MOST_ONCE) };
				// 订阅相关的主题信息
				connection.subscribe(topics);
				while(true){
					Message message = connection.receive();
					byte[] payload = message.getPayload();
					OnlineUserMessage abstractMessage = SerializationUtil.deserialize(payload, OnlineUserMessage.class);
					switch (abstractMessage.getType()) {
					case AbstactMessage.ONLINE_USER_MESSAGE:
						OnlineUserMessage onlineUserMessage = (OnlineUserMessage) abstractMessage;
						System.out.println(onlineUserMessage.getUsers());
						break;
					case AbstactMessage.TEXT_MESSAGE:
						
						break;
					default:
						
						break;
					}
					message.ack();
				}
			}
		});
	}*/
	
	public static void send(String topic, TextMessage textMsg) {
		try {
			byte[] payload = MessageBuiler.build(textMsg);
			connection.publish(topic, payload, QoS.AT_LEAST_ONCE, false);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void closeConnection() {
		try {
			connection.disconnect();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static ExecutorService getExecutorService() {
		return executorService;
	}

	

}
